package com.zlzlib.adb;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
 * adb执行工具
 *
 * @DateTime: 2023/5/15 16:46
 * @Author zlz
 * @Version 1.0
 */
public class AdbUtil {

    public static Logger logger = Logger.getLogger("AdbUtil");


//    public static void main(String[] args) {
//    }

    /**
     * 执行命令
     *
     * @param cmd 命令
     * @return 执行结果
     */
    public static String exeCmd(String cmd) {
        return exeCmd(cmd, null);
    }

    /**
     * 执行命令
     *
     * @param cmd  命令
     * @param file 执行的工作目录
     * @return 执行结果
     */
    public static String exeCmd(String cmd, File file) {
        Process process;
        try {
            process = Runtime.getRuntime().exec(cmd, null, file);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        String res = inputStream2String(process.getInputStream());
        String fileLog = file == null ? "" : " file: " + file.getAbsolutePath();
        logger.info("exeCmd: " + cmd + fileLog + "\n res: " + res);
        return res;
    }

    /**
     * 执行命令返回一个进程
     *
     * @param cmd 命令
     * @return 进程
     */
    public static Process exeCmdProcess(String cmd) {
        return exeCmdProcess(cmd, null);
    }

    /**
     * 执行命令返回一个进程
     *
     * @param cmd  命令
     * @param file 执行的工作目录
     * @return 进程
     */
    public static Process exeCmdProcess(String cmd, File file) {
        Process process;
        try {
            process = Runtime.getRuntime().exec(cmd, null, file);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        String fileLog = file == null ? "" : " file: " + file.getAbsolutePath();
        logger.info("exeCmdProcess: " + cmd + fileLog);
        return process;
    }

    /**
     * 转化数据
     */
    public static String inputStream2String(InputStream inputStream) {
        StringBuilder result = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        try {
            String temp;
            while ((temp = br.readLine()) != null) {
                result.append(temp).append("\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result.toString();
    }

    public static String result(String res) {
        return res.replace("\n", "");
    }

    public static boolean connect(String ip, int port) {
        String res = AdbUtil.exeCmd(AdbCmd.connect(ip, port));
        if (res == null) {
            return false;
        }
        if (res.contains("connected")) {
            return true;
        } else if (res.contains("authenticate")) {
            AdbUtil.exeCmd(AdbCmd.connect(ip, port));
            return true;
        }
        return false;
    }

    public static boolean fileIsExit(String ip, String filePath) {
        String res = AdbUtil.exeCmd(AdbCmd.fileIsExit(ip, filePath));
        if (res == null) {
            return false;
        }
        return !res.contains("No such file or directory");
    }

    public static String[] findDeviceSize(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceSize(ip));
        if (res == null) {
            return new String[]{};
        }
        String[] x = result(res).split(":");
        if (x.length < 2) {
            return new String[]{};
        }
        return x[1].replace(" ", "").split("x");
    }

    public static String findTopWindowApk(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findTopWindowApk(ip));
        if (res == null) {
            return "";
        }
        return result(res).replace("mFocusedWindow=Window", "");
    }

    public static String findDeviceVersionName(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceVersionName(ip));
        if (res == null) {
            return "";
        }
        return result(res);
    }

    public static String findDeviceVersionCode(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceVersionCode(ip));
        if (res == null) {
            return "";
        }
        return result(res);
    }

    public static String findDeviceModel(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceModel(ip));
        if (res == null) {
            return "";
        }
        return result(res);
    }

    public static String findDeviceBrand(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceBrand(ip));
        if (res == null) {
            return "";
        }
        return result(res);
    }

    public static String findDeviceDensity(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceDensity(ip));
        if (res == null) {
            return "";
        }
        return result(res).replace("Physical", "")
                .replace("density:", "")
                .replace(" ", "").replace("Override", "->");
    }

    public static String findDeviceBrightnessValue(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.findDeviceBrightnessValue(ip));
        if (res == null) {
            return "";
        }
        return result(res);
    }

    public static boolean forwardDevice(String ip, int pcPort, int devicePort) {
        String res = AdbUtil.exeCmd(AdbCmd.forwardDevice(ip, pcPort, devicePort));
        if (res == null) {
            return false;
        }
        return result(res).equals(String.valueOf(pcPort)) || result(res).isEmpty();
    }

    public static boolean setDeviceBrightnessValue(String ip, int value) {
        String res = AdbUtil.exeCmd(AdbCmd.setDeviceBrightnessValue(ip, value));
        if (res == null) {
            return false;
        }
        return result(res).isEmpty();
    }

    public static boolean setDeviceDensity(String ip, int value) {
        String res = AdbUtil.exeCmd(AdbCmd.setDeviceDensity(ip, value));
        if (res == null) {
            return false;
        }
        return result(res).isEmpty();
    }

    public static boolean setAudio(String ip, int version, AudioTypeEnum type, int volume) {
        String res = AdbUtil.exeCmd(AdbCmd.setAudio(ip, version, type.getValue(), volume));
        if (res == null) {
            return false;
        }
        if (version >= 26) {
            return !result(res).contains("Exception");
        } else {
            return result(res).contains("Parcel(00000000    '....')");
        }
    }

    public static String getCurrentAudio(String ip, int version, AudioTypeEnum type) {
        String res = AdbUtil.exeCmd(AdbCmd.getCurrentAudio(ip, version, type.getValue()));
        if (res == null) {
            return "";
        }
        if (version >= 26) {
            //取出当前音量
            return resCurrentMaxAudio(result(res), false);
        } else {
            return resNormalAudio(result(res));
        }
    }

    public static String getMaxAudio(String ip, int version, AudioTypeEnum type) {
        String res = AdbUtil.exeCmd(AdbCmd.getMaxAudio(ip, version, type.getValue()));
        if (res == null) {
            return "";
        }
        if (version >= 26) {
            //取出最大音量
            return resCurrentMaxAudio(result(res), true);
        } else {
            return resNormalAudio(result(res));
        }
    }

    private static String resNormalAudio(String res) {
        //Result: Parcel(00000000 00000005   '........')
        String[] ss1 = res.split("\\(");
        if (ss1.length > 1) {
            String[] ss2 = ss1[1].split(" ");
            if (ss2.length > 2) {
                String value = ss2[1];
                //16进制转换
                try {
                    return String.valueOf(Integer.parseInt(value, 16));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return "";
    }

    private static String resCurrentMaxAudio(String res, boolean isMax) {
        // [v] will control stream=3 (STREAM_MUSIC)
        // [v] will get volume
        // [v] Connecting to AudioService
        // [v] volume is 0 in range [0..100]
        String[] ss1 = res.split("volume");
        if (ss1.length < 3) {
            return "";
        }
        String[] ss2 = ss1[2].split(" ");
        if (ss2.length < 6) {
            return "";
        }
        if (isMax) {
            String[] ss3 = ss2[5].replace("[", "")
                    .replace("]", "").split("\\.\\.");
            if (ss3.length < 2) {
                return "";
            }
            return ss3[1];
        } else {
            return ss2[2];
        }
    }

    public static boolean setSystemTime(String ip, int version, long time) {
        String res = AdbUtil.exeCmd(AdbCmd.setSystemTime(ip, version, time));
        if (res == null) {
            return false;
        }
        return result(res).contains(AdbCmd.getMyDateFormat("HH:mm:ss").format(time));
    }

    public static String getPackagePath(String ip, String name) {
        String res = AdbUtil.exeCmd(AdbCmd.getPackagePath(ip, name));
        if (res == null) {
            return "";
        }
        List<String> list = getPackageList(res);
        for (String s : list) {
            //拆分最后一个=
            if (s.endsWith(name)) {
                int index = s.lastIndexOf("=");
                if (index > 0) {
                    return s.substring(0, index);
                }
            }
        }
        return "";
    }

    public static List<String> getOtherPackages(String ip) {
        String res = AdbUtil.exeCmd(AdbCmd.getOtherPackages(ip, ""));
        if (res == null) {
            return new ArrayList<>();
        }
        return getPackageList(res);
    }

    private static List<String> getPackageList(String res) {
        String[] ss = res.split("\n");
        List<String> list = new ArrayList<>(ss.length);
        for (String s : ss) {
            if (!s.isEmpty()) {
                list.add(s.replace("package:", ""));
            }
        }
        return list;
    }

    public static boolean installApk(String ip, String apkPath, boolean isUpdate) {
        String res = AdbUtil.exeCmd(AdbCmd.installApk(ip, apkPath, isUpdate));
        if (res == null) {
            return false;
        }
        return result(res).contains("Success");
    }

    public static boolean uninstallApk(String ip, String packageName) {
        String res = AdbUtil.exeCmd(AdbCmd.uninstallApk(ip, packageName));
        if (res == null) {
            return false;
        }
        return result(res).contains("Success");
    }

    public static boolean closeApk(String ip, String packageName) {
        String res = AdbUtil.exeCmd(AdbCmd.closeApk(ip, packageName));
        if (res == null) {
            return false;
        }
        return result(res).isEmpty();
    }

    public static boolean openApk(String ip, String packageName, String page) {
        String res = AdbUtil.exeCmd(AdbCmd.openApk(ip, packageName, page));
        if (res == null) {
            return false;
        }
        return !result(res).contains("Error");
    }

    public static boolean openService(String ip, String packageName, String page) {
        String res = AdbUtil.exeCmd(AdbCmd.openService(ip, packageName, page));
        if (res == null) {
            return false;
        }
        return !result(res).contains("Error");
    }

    public static boolean openServiceForeground(String ip, String packageName, String page) {
        String res = AdbUtil.exeCmd(AdbCmd.openServiceForeground(ip, packageName, page));
        if (res == null) {
            return false;
        }
        return !result(res).contains("Error");
    }

    public static String findApkVersionName(String ip, String packageName) {
        String res = AdbUtil.exeCmd(AdbCmd.findApkVersionName(ip, packageName));
        if (res == null) {
            return "";
        }
        String[] ss = result(res).split("=");
        if (ss.length > 1) {
            return ss[1];
        }
        return result(res).replace("versionName=", "");
    }

    public static Process getLogcat(String ip, String key) {
        return exeCmdProcess(AdbCmd.getLogcat(ip, key));
    }
}
